package com.github.zdg.recyclerview;

import android.content.Context;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.view.ViewGroup;

import java.lang.reflect.ParameterizedType;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;


/**
 * Created by zoudong on 2017/3/7.
 */
public class RecyclerListAdapter<D, VH extends ItemViewHolder<D>> extends BaseRecyclerAdapter<VH> {
    public static final String TAG = "RecyclerListAdapter";
    private static final int BASE_ITEM_TYPE_HEADER = 100_000;
    private static final int BASE_ITEM_TYPE_FOOTER = 200_000;
    protected List<D> mList;
    public RecyclerListAdapter(Context mContext, List<D> list) {
        super(mContext);
        this.mList = list;
    }

    @Override
    public VH onCreateViewHolder(ViewGroup parent, int viewType) {
        if (isHeaderType(viewType)) {
            ItemViewHolder viewHolder = (ItemViewHolder) getHeadOrFooterViewHolder(viewType);
            if (viewHolder != null) {
                return (VH) viewHolder;
            }
        }
        if (isFooterType(viewType)) {
            ItemViewHolder viewHolder = (ItemViewHolder) getHeadOrFooterViewHolder(viewType);
            if (viewHolder != null) {
                return (VH) viewHolder;
            }
        }
        ViewHolderFactory viewHolderFactory = mFactoryViewHolderHelper.get(viewType);
        if (viewHolderFactory != null) {
            return (VH) viewHolderFactory.onCreateViewHolder(parent);
        }
        return getVH(this, parent);
    }

    @Override
    public void onAttachedToRecyclerView(final RecyclerView recyclerView) {
        RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();
        if (manager instanceof GridLayoutManager) {
            final GridLayoutManager gridLayoutManager = (GridLayoutManager) manager;
            final GridLayoutManager.SpanSizeLookup spanSizeLookup = gridLayoutManager.getSpanSizeLookup();
            gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
                @Override
                public int getSpanSize(int position) {
                    if (spanSizeLookup.getSpanSize(position) != 1) {  //防止上次设置过得  LoadMoreHelp
                        return spanSizeLookup.getSpanSize(position);
                    }
                    int spanCount = gridLayoutManager.getSpanCount();
                    if (isHeader(position)) {
                        return spanCount;
                    }
                    int viewType = getItemViewType(position);
                    return getGridSpanSize(viewType, spanCount, position);
                }
            });
        }
    }

    protected int getGridSpanSize(int viewType, int spanCount, int position) {
        return 1;
    }

    private void setFullSpan(VH holder) {
        if (holder.itemView.getLayoutParams() instanceof StaggeredGridLayoutManager.LayoutParams) {
            StaggeredGridLayoutManager.LayoutParams params = (StaggeredGridLayoutManager.LayoutParams)
                    holder.itemView.getLayoutParams();
            params.setFullSpan(true);
        }
    }

    @Override
    public void onViewAttachedToWindow(VH holder) {
        super.onViewAttachedToWindow(holder);
        if (holder.isFullSpan()) {
            setFullSpan(holder);
        }
    }


    @Override
    public void onBindViewHolder(final VH holder, final int position) {
        if (isHeader(position)) {
            if (holder.data != null) {
                holder.onBindData(holder.data, position);
            }
        } else if (isFooter(position)) {
            if (holder.data != null) {
                holder.onBindData(holder.data, position);
            }
        } else {
//            int adapterPosition = holder.getAdapterPosition();
            final int realPosition = getRealPosition(position);
            holder.convert(getItem(realPosition), realPosition, mOnClickListenter, mLongClickListenter, mHeaderViewHolder, mFooterViewHolder);
        }
    }

    boolean isHeaderType(int type) {
        return type >= BASE_ITEM_TYPE_HEADER;
    }

    boolean isFooterType(int type) {
        return type >= BASE_ITEM_TYPE_FOOTER;
    }

    protected boolean isHeader(int position) {
        return mHeaderViewHolder.size() > position;
    }

    protected boolean isFooter(int position) {
        int count = mHeaderViewHolder.size();
        if (mList != null) {
            count += getListCount();
        }
        return position >= count;
    }

    public int getHeaderSize() {
        return mHeaderViewHolder.size();
    }

    public int getFooterSize() {
        return mFactoryViewHolderHelper.size();
    }
    @Override
    public final  int getItemViewType(int position) {
        if (isHeader(position)) {
            return mHeaderViewHolder.keyAt(position);
        }
        if (isFooter(position)) {
            return mFooterViewHolder.keyAt(position - getListCount() - mHeaderViewHolder.size());
        }
        return getViewType(getRealPosition(position));
    }

    public  int getViewType(int position) {
        return 0;
    }

    int getRealPosition(int position) {
        return position - mHeaderViewHolder.size();
    }

    public int addHeader(final ItemViewHolder itemViewHolder) {
        return addHeader(mHeaderViewHolder.size(), itemViewHolder);
    }


    public int addHeader(int type, ItemViewHolder itemViewHolder) {
        int indexofValue = mHeaderViewHolder.indexOfValue(itemViewHolder);
        if (indexofValue < 0) {
            int key = BASE_ITEM_TYPE_HEADER + type;
            int index = mHeaderViewHolder.addViewHolder(key, itemViewHolder);
            notifyItemInserted(index);
            return index;
        } else { //已经存在
            if (type != (indexofValue - BASE_ITEM_TYPE_HEADER)) {
                mHeaderViewHolder.removeViewHolder(itemViewHolder);
                int key = BASE_ITEM_TYPE_HEADER + type;
                int index = mHeaderViewHolder.addViewHolder(key, itemViewHolder);
                notifyItemMoved(indexofValue, index);
            }
            return indexofValue;
        }
    }


    public void removeHeader(final ItemViewHolder itemViewHolder) {
        int index = mHeaderViewHolder.removeViewHolder(itemViewHolder);
        if (index > -1) {
            notifyItemRemoved(index);
        }
    }

    public void removeHeader(int indexofvalue) {
        int index = mHeaderViewHolder.removeViewHolder(indexofvalue);
        if (index > -1) {
            notifyItemRemoved(indexofvalue);
        }
    }

    public int addFooter(final ItemViewHolder itemViewHolder) {
        return addFooter(mFooterViewHolder.size(), itemViewHolder);
    }


    public int addFooter(int type, ItemViewHolder itemViewHolder) {
        int indexofValue = mFooterViewHolder.indexOfValue(itemViewHolder);
        if (indexofValue < 0) {
            int key = BASE_ITEM_TYPE_FOOTER + type;
            int index = mFooterViewHolder.addViewHolder(key, itemViewHolder) + getListCount() + mHeaderViewHolder.size();
            notifyItemInserted(index);
            return index;
        } else { //已经存在
            if (type != (indexofValue - BASE_ITEM_TYPE_FOOTER)) {
                mFooterViewHolder.removeViewHolder(itemViewHolder);
                int key = BASE_ITEM_TYPE_FOOTER + type;
                int index = mFooterViewHolder.addViewHolder(key, itemViewHolder) + getListCount() + mHeaderViewHolder.size();
                notifyItemMoved(indexofValue, index);
            }
            return indexofValue;
        }
    }


    public void removeFooter(final ItemViewHolder itemViewHolder) {
        int index = mFooterViewHolder.removeViewHolder(itemViewHolder);
        if (index > -1) {
            notifyItemRemoved(getListCount() + mHeaderViewHolder.size() + index);
        }
    }

    public void removeFooter(int indexOfValue) {
        int index = mFooterViewHolder.removeViewHolder(indexOfValue);
        if (index > -1) {
            notifyItemRemoved(indexOfValue);
        }
    }

    public int getListCount() {
        if (mList == null) {
            return 0;
        }
        return mList.size();
    }

    @Override

    public int getItemCount() {
        return getListCount() + mHeaderViewHolder.size() + mFooterViewHolder.size();
    }

    ItemOnClickListenter<D> mOnClickListenter;
    ItemOnLongClickListenter<D> mLongClickListenter;


    public void setOnItemClickListenter(ItemOnClickListenter<D> onClickListenter) {
        mOnClickListenter = onClickListenter;
    }

    public void setOnItemLongClickListenter(ItemOnLongClickListenter<D> longClickListenter) {
        mLongClickListenter = longClickListenter;
    }

    public D getItem(int position) {
        if (mList == null || position > mList.size()||position<0) {
            return null;
        }
        return mList.get(position);
    }


    public List<D> getList() {
        return mList;
    }


    public void set(List<D> list) {
        mList = list;
        notifyDataSetChanged();
    }

    public void set(int index, D object) {
        if (checkIndex(index)) {
            mList.set(index, object);
            notifyItemChanged(mHeaderViewHolder.size() + index);
        }

    }

    public void remove(int index) {
        if (checkIndex(index)) {
            mList.remove(index);
            notifyItemRemoved(mHeaderViewHolder.size() + index);
        }
    }

    private boolean checkIndex(int index) {
        if (index < 0 || mList == null)
            throw new RuntimeException("index must > -1 or mList is null ");
        return mList.size() > index;
    }

    public void addAll(Collection<? extends D> collection) {
        if (mList != null) {
            int index = getItemCount();
            mList.addAll(collection);
            notifyItemRangeInserted(mHeaderViewHolder.size() + index, collection.size());
        }
    }

    public void insert(int index, D object) {
        if (mList != null) {
            int itemCount = mHeaderViewHolder.size() + index;
            if (!checkIndex(index)) {
                index = mList.size();
                itemCount = getItemCount();
            }
            mList.add(index, object);
            notifyItemInserted(itemCount);
        }
    }


    public void insert(int index, Collection<? extends D> collection) {
        if (mList != null) {
            int itemCount = mHeaderViewHolder.size() + index;
            if (!checkIndex(index)) {
                index = mList.size();
                itemCount = getItemCount();
            }
            mList.addAll(index, collection);
            notifyItemRangeInserted(itemCount, collection.size());
        }
    }

    public void remove(D object) {
        if (mList != null) {
            int indexOf = mList.indexOf(object);
            if (indexOf > -1) {
                mList.remove(indexOf);
                notifyItemRemoved(mHeaderViewHolder.size() + indexOf);
            }
        }
    }

    public void clear() {
        if (mList != null) {
            mList.clear();
            notifyDataSetChanged();
        }

    }

    public void sort(Comparator<? super D> comparator) {
        if (mList != null) {
            Collections.sort(mList, comparator);
            notifyDataSetChanged();
        }
    }

    /**
     * 获取指定参数的构造方法
     */
    private <VH> VH getVH(Object o, ViewGroup parent) {
        try {
            return ((Class<VH>) ParameterizedType.class.cast(o.getClass().getGenericSuperclass()).getActualTypeArguments()[1]).getConstructor(ViewGroup.class).newInstance(parent);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

}
